package com.njbw.train.member.domain.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.njbw.train.common.exception.BusinessException;
import com.njbw.train.common.exception.BusinessExceptionEnum;
import com.njbw.train.common.util.JwtUtil;
import com.njbw.train.common.util.SnowUtil;
import com.njbw.train.member.convert.MemberConvert;
import com.njbw.train.member.domain.MemberDomainService;
import com.njbw.train.member.entity.dto.MemberDto;
import com.njbw.train.member.entity.dto.MemberLoginDto;
import com.njbw.train.member.entity.po.Member;
import com.njbw.train.member.entity.po.MemberExample;
import com.njbw.train.member.entity.vo.MemberVo;
import com.njbw.train.member.service.MemberService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class MemberDomainServiceImpl implements MemberDomainService {

    @Resource
    private MemberService memberService;

    @Override
    public int count() {
        return memberService.count();
    }

    @Override
    public long register(MemberDto memberDto) {
        // 查询是否已经存在
        Member memberDB = selectMember(memberDto.getMobile());
        // 如果手机号不存在，则插入一条记录
        if (ObjectUtil.isNull(memberDB)) {
            /**
             * 做法 1：
             * 带验证码的注册可以采用这种方式，有验证码，说明手机号是本人用，原来注册过的，就不用再保存了，
             * 直接把数据库返回。
             * 这个接口做成既可以是注册，也可以是登录。
             */
            // return memberList.get(0).getId();

            // 做法 2：抛出一个异常，告诉用户，当前手机号已经被注册了
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_EXIST);
        }

        // 注册操作
        Member member = new Member();
        // 自增 id 不适合分布式数据库，分库分表场景。适合小项目
        // UUID 会影响索引效率，因为 UUID 是无需的，用一堆无序的 ID 来构建一个有序的索引目录，性能上肯定有问题
        // 雪花算法由 Twitter 公司在 2014 年开源 scala 语言版本
        // 雪花算法生成的 ID 是一个 long 类型的数字，通常我们用 64 位二进制来表示一个 ID
        member.setId(SnowUtil.getSnowFlakeNextId());
        member.setMobile(memberDto.getMobile());
        memberService.insert(member);
        return member.getId();
    }

    @Override
    public void sendCode(MemberDto memberDto) {
        Member memberDB = selectMember(memberDto.getMobile());
        // 如果手机号不存在，则插入一条记录
        if (ObjectUtil.isNull(memberDB)) {
            log.info("手机号不存在，插入一条记录：{}", memberDto.getMobile());
            Member member = new Member();
            member.setId(SnowUtil.getSnowFlakeNextId());
            member.setMobile(memberDto.getMobile());
            memberService.insert(member);
        } else {
            log.info("手机号存在，不插入记录：{}", memberDto.getMobile());
        }
        // 生成验证码
        String code = RandomUtil.randomString(6);
        log.info("生成短信验证码：{}", code);
        // 保存短信记录表：手机号，短信验证码，有效期，是否已使用，业务类型，发送时间，使用时间
        log.info("保存短信记录表");

        // 对接短信通道，发送短信
        log.info("对接短息通道");
    }


    @Override
    public MemberVo login(MemberLoginDto memberLoginDto) {
        String mobile = memberLoginDto.getMobile();
        String code = memberLoginDto.getCode();
        Member memberDB = selectMember(mobile);
        if (ObjectUtil.isNull(memberDB)) {
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_NOT_EXIST);
        }

        // 校验短信验证码
        if (!"8888".equals(code)) {
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_CODE_ERROR);
        }
        MemberVo memberVo = MemberConvert.INSTANCE.convertPoToVo(memberDB);
        memberVo.setToken(JwtUtil.createToken(memberVo));
        return memberVo;
    }

    private Member selectMember(String mobile) {
        MemberExample memberExample = new MemberExample();
        memberExample.createCriteria().andMobileEqualTo(mobile);
        List<Member> memberList = memberService.queryByCondition(memberExample);
        if (CollUtil.isEmpty(memberList)) {
            return null;
        } else {
            return memberList.get(0);
        }
    }
}
